﻿' Copyright © Microsoft Corporation.  All Rights Reserved.
' This code released under the terms of the 
' Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
'
Option Strict On

Public Class Samples

    ' <Sample ID="SingleLineSub" Description="Single-Line Sub" MethodName="SingleLineSub" />
    Public Function SingleLineSub() As String
        Dim results As New IO.StringWriter()
        Console.SetOut(results)

        ' A single-line Sub lambda expression is a void-returning 
        ' expression suitable for use in situations which produce side
        ' effects, such as Console.WriteLine or MsgBox. 

        ' In this example, a single-line Sub provides the Action 
        ' argument for Array.ForEach. The Sub lambda expression 
        ' displays each element of the array.

        ' No parameters are necessary.

        Dim numbers = {3, 5, 19, 0, 34, 2}
        Console.Write("Results displayed by Array.ForEach: ")

        Array.ForEach(numbers, Sub(num) Console.Write(num & " "))

        Return results.ToString()
    End Function
    ' <EndSample ID="SingleLineSub" />

    ' <Sample ID="SingleLineFunction" Description="Single-Line Function" MethodName="SingleLineFunction" />
    Public Function SingleLineFunction(ByVal p1 As Object) As String
        Dim value As Integer
        If Not Integer.TryParse(p1.ToString(), value) Then _
            Return "Parameter value must be an integer."
        Dim results As New IO.StringWriter()
        Console.SetOut(results)

        ' The body of a single-line function lambda expression is a
        ' single expression. Notice that there is no As clause for the
        ' function. The return type of the function is inferred from
        ' the return type of the expression. The return type of 
        ' Labeler is String.

        ' Enter an integer for Parameter 1, and Labeler returns
        ' "positive" for values >= 0, otherwise "negative".

        Dim Labeler = Function(n As Integer) If(n >= 0, "positive",
            "negative")

        ' Function lambda expressions can be used with the standard
        ' query operators in Language-Integrated Queries (LINQ). The
        ' following query selects customers from the state of 
        ' Washington. The return type of the lambda expression is
        ' Boolean.

        Dim customers = Customer.GetCustomerList()
        Dim WACusts = customers.Where(Function(cust) cust.State =
            "Washington")

        ' Execute the query and display the results.
        Console.WriteLine()
        For Each cust In WACusts
            Console.WriteLine(cust.Name)
        Next

        Return "Labeler(" & p1.ToString & ") = " & Labeler(value) &
            vbCrLf & vbCrLf & "Customers in Washington: " &
            results.ToString()
    End Function
    ' <EndSample ID="SingleLineFunction" />

    ' <Sample ID="MultiLineSub" Description="Multiline Sub" MethodName="MultiLineSub" />
    Public Function MultiLineSub() As String
        Dim results As New IO.StringWriter()
        Console.SetOut(results)

        ' The body of a multiline Sub lambda expression is less 
        ' restricted than the single-line version, and ByRef 
        ' parameters can be used effectively. In the following 
        ' example, each element in parameter intArray is incremented
        ' by 1. 

        ' No parameters are necessary.

        Dim numbers = {13, 0, 34, 71, 2}
        Dim Increment = Sub(ByRef intArray() As Integer)
                            For i = 0 To intArray.Length - 1
                                intArray(i) += 1
                            Next
                        End Sub

        Increment(numbers)

        Console.Write("Array elements after Increment: ")
        For Each num In numbers
            Console.Write(num & " ")
        Next

        Return results.ToString()
    End Function
    ' <EndSample ID="MultiLineSub" />

    ' <Sample ID="MultiLineFunction" Description="Multiline Function" MethodName="MultiLineFunction" />
    Public Function MultiLineFunction(ByVal p1 As Object) As String
        Dim value As Integer
        If Not Integer.TryParse(p1.ToString(), value) Then _
            Return "Parameter value must be an integer."

        ' Using a multiline lambda expression in this example allows
        ' you to call the Randomize method, and then to calculate and
        ' return a random integer. An As clause to specify the return
        ' type of the function is optional here, because the type can
        ' be inferred from the body.

        ' Enter a positive integer for Parameter 1, and Randomizer
        ' will return a random integer between 1 and the argument 
        ' value.

        Dim Randomizer = Function(max As Integer)
                             Randomize()
                             Return CInt(Int(max * Rnd() + 1))
                         End Function

        Return "Randomizer(" & value & ") = " & Randomizer(value)
    End Function
    ' <EndSample ID="MultiLineFunction" />


    ' <Sample ID="MultiLineFunctionWithAsClause" Description="Multiline Function with As Clause" MethodName="MultiLineFunctionWithAsClause" />
    Public Function MultiLineFunctionWithAsClause(ByVal p1 As Object,
                                                  ByVal p2 As Object)As String
        Dim value1 As Integer
        If Not Integer.TryParse(p1.ToString(), value1) Then _
            Return "Parameter 1 value must be an integer."
        Dim value2 As Integer
        If Not Integer.TryParse(p2.ToString(), value2) Then _
            Return "Parameter 2 value must be an integer."
        Dim results As New IO.StringWriter()
        Console.SetOut(results)

        ' The following example demonstrates a situation in which an
        ' as clause can be used to change the return type of a multiline 
        ' function lambda expression , rather than relying on the compiler 
        ' to infer the type

        ' Enter integers for Parameter 1 and Parameter 2.

        Dim Greater = Function(n As Integer, p As Single) As Double
                          If n > p Then
                              Console.WriteLine(n &
                                  " is greater than or equal to " & p)
                              Return n
                          Else
                              Console.WriteLine(p &
                                  " is greater than or equal to " & n)
                              Return p
                          End If
                      End Function

        Console.Write("Greater(" & value1 & ", " & value2 & ") = ")
        Console.WriteLine(Greater(value1, value2))

        Return results.ToString()
    End Function
    ' <EndSample ID="MultiLineFunctionWithAsClause" />
    Function Announce(ByVal bigger As Integer, ByVal smaller As Integer) As String
        Return bigger & " is greater than or equal to " & smaller

    End Function

    ' <Sample ID="AssignFunctionToAction" Description="Assign Function to Action" MethodName="AssignFunctionToAction" />
    Public Function AssignFunctionToAction() As String
        Dim results As New IO.StringWriter()
        Console.SetOut(results)

        ' Relaxed delegate conversion allows a function lambda 
        ' expression to be used where a Sub lambda is expected. In the
        ' following example, which doubles and displays each element 
        ' of an array, a function lambda expression is sent in for 
        ' an Action parameter. The return value is ignored.

        ' No parameters are required.

        Dim numbers = {5, 19, 0, 34}
        Console.Write("Doubled values from Array.ForEach: ")
        Array.ForEach(numbers, Function(num)
                                   Dim times2 = num * 2
                                   Console.Write(times2 & " ")
                                   Return times2
                               End Function)

        Return results.ToString()
    End Function
    ' <EndSample ID="AssignFunctionToAction" />


    ' <Sample ID="RecursiveLambda" Description="Recursive Function" MethodName="RecursiveLambda" />
    Public Function RecursiveLambda(ByVal p1 As Object) As String
        Dim value As Integer
        If Not Integer.TryParse(p1.ToString(), value) Then _
            Return "Parameter value must be an integer."

        ' To write a recursive function lambda expression, you must 
        ' use a Func delegate, as shown in the following example.

        ' Enter a positive integer between 0 and 12 for Parameter 1.

        Dim Factorial As Func(Of Integer, Integer) =
            Function(n)
                Return If(n = 0, 1, n * Factorial(n - 1))
            End Function

        Return "Factorial(" & p1.ToString() & ") = " &
            Factorial(value)
    End Function
    ' <EndSample ID="RecursiveLambda" />
End Class
